#pragma once

#include "CoreMinimal.h"

#include "DataStructures.generated.h"

// We use Y=up coordinate system
#define DIRECTION_UP 0
#define DIRECTION_DOWN 1
#define DIRECTION_X_PLUS 2
#define DIRECTION_X_MINUS 3
#define DIRECTION_Z_PLUS 4
#define DIRECTION_Z_MINUS 5

#define TEXTURE_TYPE_COLOR 0
#define TEXTURE_TYPE_NORMAL 1
#define TEXTURE_TYPE_SPECULAR 2

// #define BlockIndex(x, y, z)  ((y & 0xF) << 8) | ((z & 0xF) << 4) | (x & 0xF)

FORCEINLINE int BlockIndex(int x, int y, int z) {
	return (((z & 0xF) << 8) | ((x & 0xF) << 4) | (y & 0xF)) & 0xFFF; //short
}

/*
 * Here we use Y=up coordinate system instead of UE's system
 */
USTRUCT(BlueprintType)
struct FChunkCoordinate {
	GENERATED_BODY()

	UPROPERTY(VisibleAnywhere)
		int32 x = 0;
	UPROPERTY(VisibleAnywhere)
		int32 z = 0;
	UPROPERTY(VisibleAnywhere)
		uint8 y = 0;

	bool IsInSameColumn(FChunkCoordinate& target) {
		if (x == target.x && z == target.z) return true;
		return false;
	}

	bool Equals(const FChunkCoordinate& target) {
		if (x == target.x && z == target.z && y == target.y) return true;
		return false;
	}

	FChunkCoordinate GetUpper() {
		return FChunkCoordinate{x, z, (uint8) (y+1)};
	}
	FChunkCoordinate GetLower() {
		return FChunkCoordinate{ x, z, (uint8) (y-1) };
	}
	FChunkCoordinate GetXPlus() {
		return FChunkCoordinate{ x + 1, z, y };
	}
	FChunkCoordinate GetXMinus() {
		return FChunkCoordinate{ x - 1, z, y };
	}
	FChunkCoordinate GetZPlus() {
		return FChunkCoordinate{ x, z + 1, y };
	}
	FChunkCoordinate GetZMinus() {
		return FChunkCoordinate{ x, z - 1, y };
	}

	bool operator==(const FChunkCoordinate& target) const {
		if (x == target.x && z == target.z && y == target.y) return true;
		return false;
	}

	bool operator!=(const FChunkCoordinate& target) const {
		if (x == target.x && z == target.z && y == target.y) return false;
		return true;
	}
};

struct ChunkData {
	uint16 id[16 * 16 * 16];
	uint16 meta[16 * 16 * 16];
};

struct TextureInfo {
	float start_x;
	float start_y;
	float end_x;
	float end_y;
};
